package net.gdface.guava;

import static net.gdface.guava.ObjectDeepEquivalence.DEEP_EQUIVALENCE;

import com.google.common.base.Equivalence;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;

import net.gdface.reflection.MethodUtils;

/**
 * @author guyadong
 * @since 2.9.6
 */
public class ObjectDeepEquals {
	
	/**
	 * 反射调用
	 * {@link CacheBuilder#keyEquivalence(Equivalence)}和{@link CacheBuilder#valueEquivalence(Equivalence)}方法
	 * 
	 * @param builder
	 * @param methodName
	 * @param equivalence
	 * @return always builder
	 */
	@SuppressWarnings("unchecked")
	private static CacheBuilder<Object, Object> setBuilderDeepEquivalence(CacheBuilder<Object, Object> builder,
			String methodName, Equivalence<Object> equivalence) {
		if (builder != null && equivalence != null) {
			// 等价于 builder.keyEquivalence(DEEP_EQUIVALENCE);
			try {
				return (CacheBuilder<Object, Object>) MethodUtils.invokeMethod(builder, methodName,
						new Object[] { equivalence }, true);
			} catch (Exception e) {
				Throwables.throwIfUnchecked(e);
				throw new RuntimeException(e);
			}
		}
		return builder;
	}
	/**
	 * 为{@link CacheBuilder}实例指定KEY执行深度比较
	 * @param builder
	 * @return always builder
	 */
	public static final CacheBuilder<Object, Object> keyDeepEqual(CacheBuilder<Object, Object> builder){
		// 等价于 builder.keyEquivalence(DEEP_EQUIVALENCE);
		return setBuilderDeepEquivalence(builder,"keyEquivalence", DEEP_EQUIVALENCE);
	}
	/**
	 * 为{@link CacheBuilder}实例指定VALUE执行深度比较
	 * @param builder
	 * @return always builder
	 */
	public static final CacheBuilder<Object, Object> valueDeepEqual(CacheBuilder<Object, Object> builder){
		// 等价于 builder.valueEquivalence(DEEP_EQUIVALENCE);
		return setBuilderDeepEquivalence(builder,"valueEquivalence", DEEP_EQUIVALENCE);
	}
	public static final CacheBuilder<Object, Object> newBuilder(){
		return newBuilder(DEEP_EQUIVALENCE,DEEP_EQUIVALENCE);
	}
	static final CacheBuilder<Object, Object> newBuilder(
			Equivalence<Object> keyEquivalence,
			Equivalence<Object> valueEquivalence){
		CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
		if(keyEquivalence != null){
			// 等价于 builder.keyEquivalence(keyEquivalence);
			setBuilderDeepEquivalence(builder,"keyEquivalence", keyEquivalence);
		}
		if(valueEquivalence != null){
			// 等价于 builder.valueEquivalence(valueEquivalence);
			setBuilderDeepEquivalence(builder,"valueEquivalence", valueEquivalence);
		}
		return builder;
	}
}
